#pragma once
#include "Socket.hpp"
#include "log.hpp"
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>
#include <functional>

using namespace LogModule;
class Request
{
public:
    Request() {}

    Request(int x, int y, int character) : _x(x), _y(y), _character(character)
    {
    }

    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["character"] = _character;

        // Json::StreamWriterBuilder sbuilder;
        // std::unique_ptr<Json::StreamWriter> writer(sbuilder.newStreamWriter());
        // std::stringstream ss;
        // writer->write(root, &ss);
        // return ss.str();
        Json::FastWriter writer;
        std::string ret = writer.write(root);
        return ret;
    }

    bool DeSerialize(const std::string str)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(str, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _character = root["character"].asInt();
        }
        return ok;
    }

    ~Request() {}

    int X() { return _x; }
    int Y() { return _y; }
    int Character() { return _character; }

private:
    int _x;
    int _y;
    int _character;
};

class Response
{
public:
    Response() {}
    Response(int result, int code) : _result(result), _code(code){}

    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        std::string ret = writer.write(root);
        return ret;
    }

    bool Deserialize(const std::string &str)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(str, root);
        if (ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }

    void Output()
    {
        std::cout << "-------------response-------------"<< std::endl;
        std::cout << "-----result:" << _result << "-----code" << _code << "----"<<std::endl;
        std::cout << "----------------------------------"<<std::endl;
    }

    void SetResult(int result)
    {
        _result = result;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    ~Response() {}

private:
    int _result;
    int _code;
    // 关于结果的正确与否， 0：正确
};

const std::string sep = "\r\n";

using Pfunc_t = std::function<Response(Request)>;
class Protocol
{
public:
    Protocol() {}
    Protocol(Pfunc_t f) : _func(f){}

    std::string Encode(const std::string &str)
    {
        std::string len = std::to_string(str.size());
        return len + sep + str + sep;
    }

    bool Decode(std::string &str, std::string *package)
    {
        // 如果没有\r\n直接结束
        ssize_t pos = str.find(sep);
        if (pos == std::string::npos)
            return false;

        // 如果长度不够一条json串，也结束
        std::string str_len = str.substr(0, pos);
        int len = std::stoi(str_len);
        len += str_len.size() + 2 * sep.size();
        if (str.size() < len)
            return false;

        // 截取对应的串。
        *package = str.substr(pos + sep.size(), len);
        str.erase(0, len);
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        std::string read_queue;
        while (true)
        {
            int n = sock->Recv(read_queue);
            if (n > 0)
            {
                std::string package;
                while (Decode(read_queue, &package))
                {
                    // 1、反序列化
                    Request req;
                    if(!req.DeSerialize(package)) continue;

                    // 2、交给对应的回调函数执行得到结果。
                    Response res = _func(req);

                    // 3、对结果进行序列化
                    std::string json_str = res.Serialize();

                    // 4、序列化之后加上自定义协议
                    std::string send_ret = Encode(json_str);

                    // 5、返回服务器
                    sock->Send(send_ret);
                }
            }
            else if (n == 0)
            {
                LOG((int)LogLevel::INFO) << "读取完成！";
                break;
            }
            else
            {
                LOG((int)LogLevel::WARNING) << "读取失败！";
                break;
            }
        }
    }

    bool GetResponse(std::shared_ptr<Socket> &sock, std::string &read_queue, Response &res)
    {
        while (true)
        {
            std::string package;
            int n = sock->Recv(read_queue);
            if (n > 0)
            {
                //1、去除报头
                while (Decode(read_queue, &package))
                {
                    //2、反序列化
                    if(!res.Deserialize(package)) continue;
                    //3、打印结果
                    res.Output();
                }
                return true;
            }
            else if(n == 0)
            {
                LOG((int)LogLevel::WARNING) << "服务器退出！";
                return false;
            }
            else
            {
                LOG((int)LogLevel::ERROR) << "读取失败！";
                return false;
            }
        }
    }

    std::string BuiltOneGroupData(int x, int y, int oper)
    {
        Request req(x, y, oper);
        std::string req_str = req.Serialize();
        req_str = Encode(req_str);
        return req_str;
    }

private:
    Pfunc_t _func;
};